package cn.clx.ymcc.service.impl;

import cn.clx.ymcc.constants.BaseConstant;
import cn.clx.ymcc.constants.YmccExceptionError;
import cn.clx.ymcc.domain.Login;
import cn.clx.ymcc.domain.User;
import cn.clx.ymcc.domain.UserAccount;
import cn.clx.ymcc.domain.UserBaseInfo;
import cn.clx.ymcc.dto.RedisDto;
import cn.clx.ymcc.dto.RegisterDto;
import cn.clx.ymcc.feign.LoginFeignClient;
import cn.clx.ymcc.mapper.UserMapper;
import cn.clx.ymcc.result.JSONResult;
import cn.clx.ymcc.service.IUserAccountService;
import cn.clx.ymcc.service.IUserBaseInfoService;
import cn.clx.ymcc.service.IUserService;
import cn.clx.ymcc.util.AssertUtil;
import cn.clx.ymcc.util.BitStatesUtils;
import cn.clx.ymcc.util.StrUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author clx
 * @since 2022-07-15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private LoginFeignClient loginFeignClient;
    @Autowired
    private IUserAccountService userAccountService;
    @Autowired
    private IUserBaseInfoService userBaseInfoService;

    @Override
    public User selectByPhone(String phone) {
        return userMapper.selectByPhone(phone);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)  //开启全局事务
    public void register(RegisterDto dto) {
        //校验参数
        AssertUtil.isNotEmpty(dto.getPassword(), YmccExceptionError.USER_PASSWOERD_NULL.getMessage());
        AssertUtil.isNotNull(dto.getSmsCode(),YmccExceptionError.USER_SMSCODE_NULL.getMessage());
        String phone = dto.getMobile();
        String key = String.format(BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX, phone);
        RedisDto o = (RedisDto) redisTemplate.opsForValue().get(key);
        AssertUtil.isNotNull(o, YmccExceptionError.EXCEPTION_REGISTER_TIME_OUT_ERROR.getMessage());
        //比对验证码是否正确
        AssertUtil.isEquals(dto.getSmsCode(),o.getCode(),YmccExceptionError.EXCEPTION_REGISTER_COMPARISON_ERROR.getMessage());
        User user = selectByPhone(phone);
        AssertUtil.isNull(user,YmccExceptionError.EXCEPTION_REGISTER_REPEAT_ERROR.getMessage());

        //调用微服务，保存Login
        JSONResult result = savelogin(dto);
        AssertUtil.isTrue(result.isSuccess(),result.getMessage());
        Object data = result.getData();
        String jsonObject= JSON.toJSONString(data);
        //将json转成需要的对象
        Login login= JSONObject.parseObject(jsonObject,Login.class);
        AssertUtil.isNotNull(result.getData(),YmccExceptionError.USER_SAVE_NOT.getMessage());
        //保存t_user  t_user_account  t_user_base_info
        User saveuser = saveuser(phone, login);
        saveuserAccount(saveuser);
        saveUserBaseInfo(dto, saveuser);


    }

    private void saveUserBaseInfo(RegisterDto dto, User saveuser) {
        UserBaseInfo userBaseInfo = new UserBaseInfo();
        userBaseInfo.setCreateTime(System.currentTimeMillis());
        userBaseInfo.setId(saveuser.getId());
        userBaseInfo.setRegChannel(dto.getRegChannel());
        userBaseInfoService.insert(userBaseInfo);
    }

    /**
     * 保存user_account
     * @param saveuser
     */
    private void saveuserAccount(User saveuser) {
        UserAccount userAccount = new UserAccount();
        userAccount.setCreateTime(System.currentTimeMillis());
        userAccount.setId(saveuser.getId());
        userAccountService.insert(userAccount);
    }

    private User saveuser(String phone, Login login) {
        User user;
        user = new User();
        user.setCreateTime(System.currentTimeMillis());
        user.setLoginId(login.getId());
        user.setPhone(phone);
        user.setNickName(phone);
        //设置该用户的邀请码
        user.setCode(StrUtils.getComplexRandomString(4));
        //设置位状态
        long addState = BitStatesUtils.addState(BitStatesUtils.OP_ACTIVED, BitStatesUtils.OP_REGISTED);
        addState = BitStatesUtils.addState(addState, BitStatesUtils.OP_AUTHED_PHONE);
        user.setBitState(addState);
        userMapper.insert(user);
        return user;
    }

    /**
     * 保存login表
     * @param dto
     */
    private JSONResult savelogin(RegisterDto dto) {
        Login login = new Login();
        login.setUsername(dto.getMobile());
        login.setPassword(dto.getPassword());
        login.setType(1);
        JSONResult insert = loginFeignClient.insert(login);
        return insert;
    }

}
